/* ----------------------- 系统头文件引入 ----------------------------------*/
#include "stdlib.h"   // 标准库（提供内存操作、通用工具函数）
#include "string.h"   // 字符串操作库（提供memcpy、strlen等函数）

/* ----------------------- 平台适配头文件引入 ------------------------------*/
#include "port.h"     // 平台适配层（封装硬件相关接口，如定时器、串口操作）

/* ----------------------- Modbus头文件引入 --------------------------------*/
//#include "mb.h"       // Modbus公共头文件（此处注释，因本文件仅依赖主机相关定义）
#include "mb_m.h"     // Modbus主机核心头文件（定义主机状态、事件、错误码）
#include "mbframe.h"  // Modbus帧结构头文件（定义PDU偏移、帧长度等通用结构）
#include "mbproto.h"  // Modbus协议头文件（定义功能码、异常码、协议常量）
#include "mbconfig.h" // Modbus配置头文件（定义功能码使能、从机数量等编译选项）

/* ----------------------- 宏定义：Modbus PDU结构映射 -----------------------*/
// --------------------------- 读保持寄存器相关 ---------------------------
#define MB_PDU_REQ_READ_ADDR_OFF                ( MB_PDU_DATA_OFF + 0 )  // 读请求：寄存器起始地址偏移（2字节，大端序）
#define MB_PDU_REQ_READ_REGCNT_OFF              ( MB_PDU_DATA_OFF + 2 )  // 读请求：寄存器数量偏移（2字节）
#define MB_PDU_REQ_READ_SIZE                    ( 4 )                    // 读请求：PDU数据区最小长度（2字节地址+2字节数量）
#define MB_PDU_FUNC_READ_REGCNT_MAX             ( 0x007D )               // 读请求：单次最大寄存器数（125个，Modbus协议限制）
#define MB_PDU_FUNC_READ_BYTECNT_OFF            ( MB_PDU_DATA_OFF + 0 )  // 读响应：数据字节数偏移（1字节，值=寄存器数×2）
#define MB_PDU_FUNC_READ_VALUES_OFF             ( MB_PDU_DATA_OFF + 1 )  // 读响应：寄存器数据偏移（从该位置开始存储大端序数据）
#define MB_PDU_FUNC_READ_SIZE_MIN               ( 1 )                    // 读响应：PDU数据区最小长度（至少1字节字节数）

// --------------------------- 单写保持寄存器相关 ---------------------------
#define MB_PDU_REQ_WRITE_ADDR_OFF               ( MB_PDU_DATA_OFF + 0)   // 单写请求：寄存器地址偏移（2字节，大端序）
#define MB_PDU_REQ_WRITE_VALUE_OFF              ( MB_PDU_DATA_OFF + 2 )  // 单写请求：寄存器值偏移（2字节，大端序）
#define MB_PDU_REQ_WRITE_SIZE                   ( 4 )                    // 单写请求：PDU数据区最小长度（2字节地址+2字节值）
#define MB_PDU_FUNC_WRITE_ADDR_OFF              ( MB_PDU_DATA_OFF + 0)   // 单写响应：寄存器地址偏移（与请求一致）
#define MB_PDU_FUNC_WRITE_VALUE_OFF             ( MB_PDU_DATA_OFF + 2 )  // 单写响应：寄存器值偏移（与请求一致）
#define MB_PDU_FUNC_WRITE_SIZE                  ( 4 )                    // 单写响应：PDU数据区最小长度（与请求一致）

// --------------------------- 批量写保持寄存器相关 ---------------------------
#define MB_PDU_REQ_WRITE_MUL_ADDR_OFF           ( MB_PDU_DATA_OFF + 0 )  // 批量写请求：起始地址偏移（2字节）
#define MB_PDU_REQ_WRITE_MUL_REGCNT_OFF         ( MB_PDU_DATA_OFF + 2 )  // 批量写请求：寄存器数量偏移（2字节）
#define MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF        ( MB_PDU_DATA_OFF + 4 )  // 批量写请求：数据总字节数偏移（1字节，值=寄存器数×2）
#define MB_PDU_REQ_WRITE_MUL_VALUES_OFF         ( MB_PDU_DATA_OFF + 5 )  // 批量写请求：寄存器数据偏移（从该位置开始存储）
#define MB_PDU_REQ_WRITE_MUL_SIZE_MIN           ( 5 )                    // 批量写请求：PDU数据区最小长度（2+2+1字节基础结构）
#define MB_PDU_REQ_WRITE_MUL_REGCNT_MAX         ( 0x0078 )               // 批量写请求：单次最大寄存器数（120个，Modbus协议限制）
#define MB_PDU_FUNC_WRITE_MUL_ADDR_OFF          ( MB_PDU_DATA_OFF + 0 )  // 批量写响应：起始地址偏移
#define MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF        ( MB_PDU_DATA_OFF + 2 )  // 批量写响应：寄存器数量偏移
#define MB_PDU_FUNC_WRITE_MUL_SIZE              ( 4 )                    // 批量写响应：PDU数据区最小长度（2+2字节地址+数量）

// --------------------------- 读写一体保持寄存器相关 ---------------------------
#define MB_PDU_REQ_READWRITE_READ_ADDR_OFF      ( MB_PDU_DATA_OFF + 0 )  // 读写请求：读起始地址偏移（2字节）
#define MB_PDU_REQ_READWRITE_READ_REGCNT_OFF    ( MB_PDU_DATA_OFF + 2 )  // 读写请求：读寄存器数量偏移（2字节）
#define MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF     ( MB_PDU_DATA_OFF + 4 )  // 读写请求：写起始地址偏移（2字节）
#define MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF   ( MB_PDU_DATA_OFF + 6 )  // 读写请求：写寄存器数量偏移（2字节）
#define MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF  ( MB_PDU_DATA_OFF + 8 )  // 读写请求：写数据字节数偏移（1字节）
#define MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF   ( MB_PDU_DATA_OFF + 9 )  // 读写请求：写数据偏移
#define MB_PDU_REQ_READWRITE_SIZE_MIN           ( 9 )                    // 读写请求：PDU数据区最小长度（2+2+2+2+1字节基础结构）
#define MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF  ( MB_PDU_DATA_OFF + 0 )  // 读写响应：读数据字节数偏移（1字节）
#define MB_PDU_FUNC_READWRITE_READ_VALUES_OFF   ( MB_PDU_DATA_OFF + 1 )  // 读写响应：读数据偏移
#define MB_PDU_FUNC_READWRITE_SIZE_MIN          ( 1 )                    // 读写响应：PDU数据区最小长度（至少1字节字节数）

/* ----------------------- 静态函数声明 ---------------------------------*/
// 功能：将Modbus错误码（eMBErrorCode）转换为Modbus异常码（eMBException）
eMBException    prveMBError2Exception(eMBErrorCode eErrorCode);

/* ----------------------- 函数实现开始 -----------------------------*/
// 条件编译：仅当主机RTU/ASCII模式使能时，编译以下代码
#if MB_MASTER_RTU_ENABLED || MB_MASTER_ASCII_ENABLED

// 条件编译：仅当“单写保持寄存器”功能使能时，编译以下代码
#if MB_FUNC_WRITE_HOLDING_ENABLED

/**
 * @brief  主机请求：写单个保持寄存器
 * @param  ucSndAddr    从机地址（1~MB_MASTER_TOTAL_SLAVE_NUM）
 * @param  usRegAddr    寄存器起始地址（Modbus标准1-based地址，如40001）
 * @param  usRegData    待写入的寄存器值（16位）
 * @param  lTimeOut     超时时间（-1表示永久等待）
 * @return eMBMasterReqErrCode  请求错误码（MB_MRE_NO_ERR表示成功）
 */
eMBMasterReqErrCode
eMBMasterReqWriteHoldingRegister(UCHAR ucSndAddr, USHORT usRegAddr, USHORT usRegData, LONG lTimeOut)
{
    UCHAR* ucMBFrame;          // 指向Modbus发送帧缓冲区的指针
    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;  // 初始化错误码为“无错误”

    // 1. 参数合法性检查：从机地址超出配置的总从机数 → 非法参数错误
    if (ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM)
        eErrStatus = MB_MRE_ILL_ARG;
    // 2. 尝试抢占主机运行资源：超时未抢占到 → 主机忙错误
    else if (xMBMasterRunResTake(lTimeOut) == FALSE)
        eErrStatus = MB_MRE_MASTER_BUSY;
    // 3. 抢占资源成功，构造并发送请求帧
    else {
        // 获取Modbus PDU发送缓冲区的地址
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 设置当前通信的从机地址（供后续回调函数使用）
        vMBMasterSetDestAddress(ucSndAddr);
        // 构造PDU帧：功能码（MB_FUNC_WRITE_REGISTER = 0x06，单写保持寄存器）
        ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_REGISTER;
        // 构造PDU帧：寄存器地址（大端序，高字节在前）
        ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF] = usRegAddr >> 8;
        ucMBFrame[MB_PDU_REQ_WRITE_ADDR_OFF + 1] = usRegAddr;
        // 构造PDU帧：待写入的寄存器值（大端序，高字节在前）
        ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF] = usRegData >> 8;
        ucMBFrame[MB_PDU_REQ_WRITE_VALUE_OFF + 1] = usRegData;
        // 设置PDU发送长度（基础长度+数据区长度：MB_PDU_SIZE_MIN=1字节功能码 + 4字节数据）
        vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_SIZE);
        // 发送“主机帧已发送”事件，触发底层发送逻辑
        (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT);
        // 等待请求完成（阻塞直到超时或收到响应），获取最终错误码
        eErrStatus = eMBMasterWaitRequestFinish();
    }
    // 返回请求错误码（成功/失败原因）
    return eErrStatus;
}

/**
 * @brief  主机处理：单写保持寄存器的从站响应帧
 * @param  pucFrame  指向从站响应帧缓冲区的指针
 * @param  usLen     响应帧长度（输入：接收的长度；输出：处理后的长度）
 * @return eMBException  Modbus异常码（MB_EX_NONE表示无异常）
 */
eMBException
eMBMasterFuncWriteHoldingRegister(UCHAR* pucFrame, USHORT* usLen)
{
    USHORT          usRegAddress;    // 解析出的寄存器地址
    eMBException    eStatus = MB_EX_NONE;  // 初始化异常码为“无异常”
    eMBErrorCode    eRegStatus;      // 回调函数返回的寄存器操作错误码

    // 1. 检查响应帧长度：需等于“基础长度+单写响应数据长度”（1+4=5字节）
    if (*usLen == (MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_SIZE)) {
        // 2. 解析响应帧中的寄存器地址（大端序转小端序，+1转为Modbus 1-based标准地址）
        usRegAddress = (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8);
        usRegAddress |= (USHORT)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1]);
        usRegAddress++;

        // 3. 调用保持寄存器回调函数：将响应中的数据写入应用层缓冲区（写模式）
        // 参数：响应数据地址、寄存器地址、寄存器数量（1个）、操作模式（MB_REG_WRITE=写）
        eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF],
            usRegAddress, 1, MB_REG_WRITE);

        // 4. 若回调函数返回错误，将错误码转为Modbus异常码
        if (eRegStatus != MB_ENOERR) {
            eStatus = prveMBError2Exception(eRegStatus);
        }
    }
    // 5. 响应帧长度非法 → 返回“非法数据值”异常
    else {
        eStatus = MB_EX_ILLEGAL_DATA_VALUE;
    }
    // 返回Modbus异常码（无异常/具体异常原因）
    return eStatus;
}
#endif // MB_FUNC_WRITE_HOLDING_ENABLED

// 条件编译：仅当“批量写保持寄存器”功能使能时，编译以下代码
#if MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0

/**
 * @brief  主机请求：批量写多个保持寄存器
 * @param  ucSndAddr    从机地址（1~MB_MASTER_TOTAL_SLAVE_NUM）
 * @param  usRegAddr    寄存器起始地址（Modbus 1-based地址）
 * @param  usNRegs      待写入的寄存器总数（1~MB_PDU_REQ_WRITE_MUL_REGCNT_MAX）
 * @param  pusDataBuffer 待写入的数据缓冲区（16位数组，大端序）
 * @param  lTimeOut     超时时间（-1表示永久等待）
 * @return eMBMasterReqErrCode  请求错误码（MB_MRE_NO_ERR表示成功）
 */
eMBMasterReqErrCode
eMBMasterReqWriteMultipleHoldingRegister(UCHAR ucSndAddr,
    USHORT usRegAddr, USHORT usNRegs, USHORT* pusDataBuffer, LONG lTimeOut)
{
    UCHAR* ucMBFrame;          // 指向发送帧缓冲区的指针
    USHORT                 usRegIndex = 0;     // 寄存器数据缓冲区的索引（循环用）
    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;  // 初始化错误码为“无错误”

    // 1. 参数合法性检查：从机地址超出范围 → 非法参数
    if (ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM)
        eErrStatus = MB_MRE_ILL_ARG;
    // 2. 抢占主机资源超时 → 主机忙
    else if (xMBMasterRunResTake(lTimeOut) == FALSE)
        eErrStatus = MB_MRE_MASTER_BUSY;
    // 3. 构造批量写请求帧
    else {
        // 获取PDU发送缓冲区地址
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 设置目标从机地址
        vMBMasterSetDestAddress(ucSndAddr);
        // 构造PDU功能码（MB_FUNC_WRITE_MULTIPLE_REGISTERS = 0x10，批量写）
        ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_WRITE_MULTIPLE_REGISTERS;
        // 构造PDU：起始地址（大端序）
        ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] = usRegAddr >> 8;
        ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1] = usRegAddr;
        // 构造PDU：寄存器数量（大端序）
        ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] = usNRegs >> 8;
        ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1] = usNRegs;
        // 构造PDU：数据总字节数（寄存器数×2，因每个寄存器16位=2字节）
        ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF] = usNRegs * 2;
        // 指针偏移到“数据存储区”起始位置
        ucMBFrame += MB_PDU_REQ_WRITE_MUL_VALUES_OFF;
        // 循环将待写入数据（16位）按大端序写入发送缓冲区
        while (usNRegs > usRegIndex) {
            *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;  // 写入高字节
            *ucMBFrame++ = pusDataBuffer[usRegIndex++];    // 写入低字节，索引+1
        }
        // 设置PDU发送长度：基础长度（1字节功能码）+ 基础数据区（5字节）+ 实际数据区（2×usNRegs字节）
        vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_WRITE_MUL_SIZE_MIN + 2 * usNRegs);
        // 发送“帧已发送”事件，触发底层发送
        (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT);
        // 等待请求完成，获取错误码
        eErrStatus = eMBMasterWaitRequestFinish();
    }
    // 返回请求错误码
    return eErrStatus;
}

/**
 * @brief  主机处理：批量写保持寄存器的从站响应帧
 * @param  pucFrame  指向从站响应帧缓冲区的指针
 * @param  usLen     响应帧长度（输入：接收长度；输出：处理后长度）
 * @return eMBException  Modbus异常码（MB_EX_NONE表示无异常）
 */
eMBException eMBMasterFuncWriteMultipleHoldingRegister(UCHAR* pucFrame, USHORT* usLen)
{
    UCHAR* ucMBFrame;        // 指向主机发送帧缓冲区（用于解析请求参数）
    USHORT          usRegAddress;     // 解析出的寄存器起始地址
    USHORT          usRegCount;       // 解析出的寄存器数量
    UCHAR           ucRegByteCount;   // 解析出的数据总字节数

    eMBException    eStatus = MB_EX_NONE;  // 初始化异常码为“无异常”
    eMBErrorCode    eRegStatus;       // 回调函数返回的错误码

    // 1. 检查响应帧长度：合法长度 或 广播请求（广播无需响应，直接返回无异常）
    if ((*usLen == MB_PDU_SIZE_MIN + MB_PDU_FUNC_WRITE_MUL_SIZE) || xMBMasterRequestIsBroadcast()) {
        // 获取主机发送帧缓冲区（因响应帧中仅包含地址和数量，需结合请求参数解析）
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 解析响应帧中的寄存器起始地址（大端序，+1转为1-based标准地址）
        usRegAddress = (USHORT)(ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF] << 8);
        usRegAddress |= (USHORT)(ucMBFrame[MB_PDU_REQ_WRITE_MUL_ADDR_OFF + 1]);
        usRegAddress++;

        // 解析响应帧中的寄存器数量（大端序）
        usRegCount = (USHORT)(ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF] << 8);
        usRegCount |= (USHORT)(ucMBFrame[MB_PDU_REQ_WRITE_MUL_REGCNT_OFF + 1]);

        // 解析响应帧中的数据总字节数
        ucRegByteCount = ucMBFrame[MB_PDU_REQ_WRITE_MUL_BYTECNT_OFF];

        // 2. 检查数据字节数合法性：字节数必须等于“寄存器数×2”（每个寄存器2字节）
        if (ucRegByteCount == 2 * usRegCount) {
            // 3. 调用回调函数：将响应数据写入应用层缓冲区（写模式）
            eRegStatus = eMBMasterRegHoldingCB(&ucMBFrame[MB_PDU_REQ_WRITE_MUL_VALUES_OFF],
                usRegAddress, usRegCount, MB_REG_WRITE);

            // 4. 回调函数错误 → 转为Modbus异常码
            if (eRegStatus != MB_ENOERR) {
                eStatus = prveMBError2Exception(eRegStatus);
            }
        }
        // 数据字节数非法 → 返回“非法数据值”异常
        else {
            eStatus = MB_EX_ILLEGAL_DATA_VALUE;
        }
    }
    // 响应帧长度非法 → 返回“非法数据值”异常
    else {
        eStatus = MB_EX_ILLEGAL_DATA_VALUE;
    }
    // 返回异常码
    return eStatus;
}
#endif // MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED > 0

// 条件编译：仅当“读保持寄存器”功能使能时，编译以下代码
#if MB_FUNC_READ_HOLDING_ENABLED > 0

/**
 * @brief  主机请求：读多个保持寄存器
 * @param  ucSndAddr    从机地址（1~MB_MASTER_TOTAL_SLAVE_NUM）
 * @param  usRegAddr    寄存器起始地址（Modbus 1-based地址）
 * @param  usNRegs      待读取的寄存器总数（1~MB_PDU_FUNC_READ_REGCNT_MAX）
 * @param  lTimeOut     超时时间（-1表示永久等待）
 * @return eMBMasterReqErrCode  请求错误码（MB_MRE_NO_ERR表示成功）
 */
eMBMasterReqErrCode
eMBMasterReqReadHoldingRegister(UCHAR ucSndAddr, USHORT usRegAddr, USHORT usNRegs, LONG lTimeOut)
{
    UCHAR* ucMBFrame;          // 指向发送帧缓冲区的指针
    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;  // 初始化错误码为“无错误”

    // 1. 从机地址非法 → 非法参数
    if (ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM)
        eErrStatus = MB_MRE_ILL_ARG;
    // 2. 抢占主机资源超时 → 主机忙
    else if (xMBMasterRunResTake(lTimeOut) == FALSE)
        eErrStatus = MB_MRE_MASTER_BUSY;
    // 3. 构造读请求帧
    else {
        // 获取PDU发送缓冲区地址
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 设置目标从机地址
        vMBMasterSetDestAddress(ucSndAddr);
        // 构造PDU功能码（MB_FUNC_READ_HOLDING_REGISTER = 0x03，读保持寄存器）
        ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READ_HOLDING_REGISTER;
        // 构造PDU：起始地址（大端序）
        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] = usRegAddr >> 8;
        ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1] = usRegAddr;
        // 构造PDU：寄存器数量（大端序）
        ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] = usNRegs >> 8;
        ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1] = usNRegs;
        // 设置PDU发送长度：基础长度（1字节功能码）+ 数据区长度（4字节）
        vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_READ_SIZE);
        // 发送“帧已发送”事件，触发底层发送
        (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT);
        // 等待请求完成，获取错误码
        eErrStatus = eMBMasterWaitRequestFinish();
    }
    // 返回请求错误码
    return eErrStatus;
}

/**
 * @brief  主机处理：读保持寄存器的从站响应帧
 * @param  pucFrame  指向从站响应帧缓冲区的指针
 * @param  usLen     响应帧长度（输入：接收长度；输出：处理后长度）
 * @return eMBException  Modbus异常码（MB_EX_NONE表示无异常）
 */
eMBException eMBMasterFuncReadHoldingRegister(UCHAR* pucFrame, USHORT* usLen)
{
    UCHAR* ucMBFrame;        // 指向主机发送帧缓冲区（解析请求参数）
    USHORT          usRegAddress;     // 解析出的寄存器起始地址
    USHORT          usRegCount;       // 解析出的寄存器数量

    eMBException    eStatus = MB_EX_NONE;  // 初始化异常码为“无异常”
    eMBErrorCode    eRegStatus;       // 回调函数返回的错误码

    // 1. 若为广播请求（读请求广播无需处理）→ 直接返回无异常
    if (xMBMasterRequestIsBroadcast()) {
        eStatus = MB_EX_NONE;
    }
    // 2. 检查响应帧长度：至少为“基础长度+最小响应长度”（1+1=2字节）
    else if (*usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READ_SIZE_MIN) {
        // 获取主机发送帧缓冲区（解析请求中的地址和数量）
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 解析寄存器起始地址（大端序，+1转为1-based标准地址）
        usRegAddress = (USHORT)(ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF] << 8);
        usRegAddress |= (USHORT)(ucMBFrame[MB_PDU_REQ_READ_ADDR_OFF + 1]);
        usRegAddress++;

        // 解析寄存器数量（大端序）
        usRegCount = (USHORT)(ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF] << 8);
        usRegCount |= (USHORT)(ucMBFrame[MB_PDU_REQ_READ_REGCNT_OFF + 1]);

        // 3. 检查响应合法性：字节数=寄存器数×2（每个寄存器2字节）且寄存器数≥1
        if ((usRegCount >= 1) && (2 * usRegCount == pucFrame[MB_PDU_FUNC_READ_BYTECNT_OFF])) {
            // 4. 调用回调函数：将响应中的寄存器数据写入应用层缓冲区（读模式）
            eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READ_VALUES_OFF],
                usRegAddress, usRegCount, MB_REG_READ);
            // 5. 回调函数错误 → 转为Modbus异常码
            if (eRegStatus != MB_ENOERR) {
                eStatus = prveMBError2Exception(eRegStatus);
            }
        }
        // 响应数据长度非法 → 返回“非法数据值”异常
        else {
            eStatus = MB_EX_ILLEGAL_DATA_VALUE;
        }
    }
    // 响应帧长度非法 → 返回“非法数据值”异常
    else {
        eStatus = MB_EX_ILLEGAL_DATA_VALUE;
    }
    // 返回异常码
    return eStatus;
}

#endif // MB_FUNC_READ_HOLDING_ENABLED > 0

// 条件编译：仅当“读写一体保持寄存器”功能使能时，编译以下代码
#if MB_FUNC_READWRITE_HOLDING_ENABLED > 0

/**
 * @brief  主机请求：读写一体操作（同时读和写保持寄存器）
 * @param  ucSndAddr        从机地址（1~MB_MASTER_TOTAL_SLAVE_NUM）
 * @param  usReadRegAddr    读操作的寄存器起始地址（Modbus 1-based）
 * @param  usNReadRegs      读操作的寄存器总数
 * @param  pusDataBuffer    写操作的待发送数据缓冲区（16位数组）
 * @param  usWriteRegAddr   写操作的寄存器起始地址（Modbus 1-based）
 * @param  usNWriteRegs     写操作的寄存器总数
 * @param  lTimeOut         超时时间（-1表示永久等待）
 * @return eMBMasterReqErrCode  请求错误码（MB_MRE_NO_ERR表示成功）
 */
eMBMasterReqErrCode
eMBMasterReqReadWriteMultipleHoldingRegister(UCHAR ucSndAddr,
    USHORT usReadRegAddr, USHORT usNReadRegs, USHORT* pusDataBuffer,
    USHORT usWriteRegAddr, USHORT usNWriteRegs, LONG lTimeOut)
{
    UCHAR* ucMBFrame;          // 指向发送帧缓冲区的指针
    USHORT                 usRegIndex = 0;     // 写数据缓冲区的索引（循环用）
    eMBMasterReqErrCode    eErrStatus = MB_MRE_NO_ERR;  // 初始化错误码为“无错误”

    // 1. 从机地址非法 → 非法参数
    if (ucSndAddr > MB_MASTER_TOTAL_SLAVE_NUM)
        eErrStatus = MB_MRE_ILL_ARG;
    // 2. 抢占主机资源超时 → 主机忙
    else if (xMBMasterRunResTake(lTimeOut) == FALSE)
        eErrStatus = MB_MRE_MASTER_BUSY;
    // 3. 构造读写一体请求帧
    else {
        // 获取PDU发送缓冲区地址
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 设置目标从机地址
        vMBMasterSetDestAddress(ucSndAddr);
        // 构造PDU功能码（MB_FUNC_READWRITE_MULTIPLE_REGISTERS = 0x17，读写一体）
        ucMBFrame[MB_PDU_FUNC_OFF] = MB_FUNC_READWRITE_MULTIPLE_REGISTERS;
        // 构造PDU：读操作的起始地址（大端序）
        ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] = usReadRegAddr >> 8;
        ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1] = usReadRegAddr;
        // 构造PDU：读操作的寄存器数量（大端序）
        ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] = usNReadRegs >> 8;
        ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1] = usNReadRegs;
        // 构造PDU：写操作的起始地址（大端序）
        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] = usWriteRegAddr >> 8;
        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1] = usWriteRegAddr;
        // 构造PDU：写操作的寄存器数量（大端序）
        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] = usNWriteRegs >> 8;
        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1] = usNWriteRegs;
        // 构造PDU：写操作的数据总字节数（寄存器数×2）
        ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_BYTECNT_OFF] = usNWriteRegs * 2;
        // 指针偏移到“写数据存储区”起始位置
        ucMBFrame += MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF;
        // 循环将写数据按大端序写入发送缓冲区
        while (usNWriteRegs > usRegIndex) {
            *ucMBFrame++ = pusDataBuffer[usRegIndex] >> 8;  // 写入高字节
            *ucMBFrame++ = pusDataBuffer[usRegIndex++];    // 写入低字节，索引+1
        }
        // 设置PDU发送长度：基础长度（1字节）+ 基础数据区（9字节）+ 写数据区（2×usNWriteRegs字节）
        vMBMasterSetPDUSndLength(MB_PDU_SIZE_MIN + MB_PDU_REQ_READWRITE_SIZE_MIN + 2 * usNWriteRegs);
        // 发送“帧已发送”事件，触发底层发送
        (void)xMBMasterPortEventPost(EV_MASTER_FRAME_SENT);
        // 等待请求完成，获取错误码
        eErrStatus = eMBMasterWaitRequestFinish();
    }
    // 返回请求错误码
    return eErrStatus;
}

/**
 * @brief  主机处理：读写一体操作的从站响应帧
 * @param  pucFrame  指向从站响应帧缓冲区的指针
 * @param  usLen     响应帧长度（输入：接收长度；输出：处理后长度）
 * @return eMBException  Modbus异常码（MB_EX_NONE表示无异常）
 */
eMBException eMBMasterFuncReadWriteMultipleHoldingRegister(UCHAR* pucFrame, USHORT* usLen)
{
    USHORT          usRegReadAddress;  // 读操作的寄存器起始地址
    USHORT          usRegReadCount;    // 读操作的寄存器数量
    USHORT          usRegWriteAddress; // 写操作的寄存器起始地址
    USHORT          usRegWriteCount;   // 写操作的寄存器数量
    UCHAR* ucMBFrame;         // 指向主机发送帧缓冲区（解析请求参数）

    eMBException    eStatus = MB_EX_NONE;  // 初始化异常码为“无异常”
    eMBErrorCode    eRegStatus;        // 回调函数返回的错误码

    // 1. 广播请求无需处理 → 直接返回无异常
    if (xMBMasterRequestIsBroadcast()) {
        eStatus = MB_EX_NONE;
    }
    // 2. 检查响应帧长度：至少为“基础长度+最小响应长度”（1+1=2字节）
    else if (*usLen >= MB_PDU_SIZE_MIN + MB_PDU_FUNC_READWRITE_SIZE_MIN) {
        // 获取主机发送帧缓冲区（解析请求中的读写参数）
        vMBMasterGetPDUSndBuf(&ucMBFrame);
        // 解析读操作的起始地址（大端序，+1转为1-based）
        usRegReadAddress = (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF] << 8U);
        usRegReadAddress |= (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_READ_ADDR_OFF + 1]);
        usRegReadAddress++;

        // 解析读操作的寄存器数量（大端序）
        usRegReadCount = (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF] << 8U);
        usRegReadCount |= (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_READ_REGCNT_OFF + 1]);

        // 解析写操作的起始地址（大端序，+1转为1-based）
        usRegWriteAddress = (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF] << 8U);
        usRegWriteAddress |= (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_ADDR_OFF + 1]);
        usRegWriteAddress++;

        // 解析写操作的寄存器数量（大端序）
        usRegWriteCount = (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF] << 8U);
        usRegWriteCount |= (USHORT)(ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_REGCNT_OFF + 1]);

        // 3. 检查读响应合法性：字节数=读寄存器数×2
        if ((2 * usRegReadCount) == pucFrame[MB_PDU_FUNC_READWRITE_READ_BYTECNT_OFF]) {
            // 4. 先调用回调函数处理写操作（将写数据写入应用层缓冲区）
            eRegStatus = eMBMasterRegHoldingCB(&ucMBFrame[MB_PDU_REQ_READWRITE_WRITE_VALUES_OFF],
                usRegWriteAddress, usRegWriteCount, MB_REG_WRITE);

            // 5. 写操作无错误 → 再调用回调函数处理读操作（将读数据写入应用层缓冲区）
            if (eRegStatus == MB_ENOERR) {
                eRegStatus = eMBMasterRegHoldingCB(&pucFrame[MB_PDU_FUNC_READWRITE_READ_VALUES_OFF],
                    usRegReadAddress, usRegReadCount, MB_REG_READ);
            }
            // 6. 任一操作错误 → 转为Modbus异常码
            if (eRegStatus != MB_ENOERR) {
                eStatus = prveMBError2Exception(eRegStatus);
            }
        }
        // 读响应数据长度非法 → 返回“非法数据值”异常
        else {
            eStatus = MB_EX_ILLEGAL_DATA_VALUE;
        }
    }
    // 返回异常码（此处省略长度非法的判断，因上方else if已覆盖合法长度，非法长度直接返回无异常？需结合协议确认）
    return eStatus;
}

#endif
#endif
